package top.rainbowecho.gateway.security.authentication.open;

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import top.rainbowecho.gateway.security.support.GatewayOpenIdDetailService;

/**
 * @author rainbow
 * @since 2019/12/20 19:05
 */
public class OpenIdAuthenticationProvider implements AuthenticationProvider {
    private GatewayOpenIdDetailService openIdDetailService;

    public void setOpenIdDetailService(GatewayOpenIdDetailService openIdDetailService) {
        this.openIdDetailService = openIdDetailService;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        OpenIdAuthenticationToken openIdAuthenticationToken = (OpenIdAuthenticationToken) authentication;
        WebAuthenticationDetails details = (WebAuthenticationDetails) openIdAuthenticationToken.getDetails();

        Object userInfo = openIdAuthenticationToken.getUserInfo();
        String openId = (String) openIdAuthenticationToken.getPrincipal();

        // 将第三方用户信息放到detailService中，用于认证时转换数据
        openIdDetailService.setUserInfo(userInfo);
        openIdDetailService.setRemoteIp(details.getRemoteAddress());
        UserDetails userDetails = openIdDetailService.loadUserByUsername(openId);

        // 认证成功后重新设置token
        OpenIdAuthenticationToken authenticationResult = new OpenIdAuthenticationToken(userDetails, userDetails.getAuthorities());
        authenticationResult.setDetails(details);

        return authenticationResult;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return OpenIdAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
